package com.duqc.tag.service.impl.strategy;

import cn.hutool.core.text.StrBuilder;
import cn.hutool.core.text.StrJoiner;
import cn.hutool.json.JSONUtil;
import com.duqc.tag.entity.ClassificationRule;
import com.duqc.tag.entity.classification.EventFilter;
import com.duqc.tag.entity.classification.EventProfile;
import com.duqc.tag.entity.classification.EventProfileRule;
import com.duqc.tag.entity.classification.EventRule;
import com.duqc.tag.entity.enumeration.TagTypeEnum;
import com.duqc.util.JdbcConnectionUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.StringJoiner;

/**
 * @ClassName TagDataEventRule
 * @Description 埋点事件规则
 * @Author duqc
 * @Date 2023/2/9
 **/
@Slf4j
@Component
@TagStrategy
public class TagDataEventRule implements TagDataStrategy {

    @Resource
    private JdbcConnectionUtil jdbcConnectionUtil;

    /**
     * 返回 type
     *
     * @return String
     */
    @Override
    public String getType() {
        return String.valueOf(TagTypeEnum.EVENT_RULE.getTagType());
    }

    /**
     * 获取标签数据
     *
     * @param objects  规则信息
     * @param relation 规则关系
     * @return List
     */
    @Override
    public List<String> calculationTag(List<ClassificationRule> objects, String relation) {
        List<String> sql = new ArrayList<>();
        objects.forEach(info -> {
            List<EventRule> eventRules = JSONUtil.toList(info.getRules(), EventRule.class);
            //sql 拼接
            List<String> sqlList = buildSql(eventRules);
            //todo or用union and用join
            if ("and".equals(info.getRelation())) {
                TagDataCommon.joinSql(sqlList, sql);
            }
        });
        StringJoiner stringJoiner = new StringJoiner(" UNION ");
        if ("or".equals(relation)) {
            sql.forEach(stringJoiner::add);
        }
        List<String> data = jdbcConnectionUtil.getData("SELECT\n" +
                "attribute_value\n" +
                "FROM event_list WHERE \n" +
                "event_id = \"szmh_cxyy_yymk_ckxq\"\n" +
                "AND attribute_id = \"$element_name\" \n" +
                "AND attribute_group_id IN (SELECT attribute_group_id\n" +
                "FROM\n" +
                "event_list\n" +
                "WHERE\n" +
                "event_id = \"szmh_cxyy_yymk_ckxq\"\n" +
                "AND create_time >= \"2022-07-18 08:40:50\"    \n" +
                "AND create_time <= \"2023-09-09 08:40:50\"\n" +
                "AND attribute_id = \"$browser_version\"\n" +
                "AND attribute_value = \"10.0.01\"\n" +
                "GROUP BY attribute_group_id\n" +
                ")   \n" +
                "GROUP BY attribute_value\n" +
                "HAVING approx_count_distinct(create_day) > 50\n" +
                "union all \n" +
                "SELECT\n" +
                "\"测一下\"");
        return data;
    }

    /**
     * 拼接sql
     *
     * @param eventRules 规则信息
     */
    private List<String> buildSql(List<EventRule> eventRules) {
        List<String> sqlList = new ArrayList<>();
        //用于测试，部分语句固定
        eventRules.forEach(info -> {
            EventProfile profileRule = info.getProfileRule();
            List<EventProfileRule> rules = profileRule.getRules();
            List<String> eventProfileSql = new ArrayList<>();
            String containSql;
            if (CollectionUtils.isEmpty(rules)) {
                containSql = "SELECT attribute_group_id FROM event_list WHERE create_time >= \"2022-07-18 08:40:50\"  AND create_time <= \"2023-09-09 08:40:50\" GROUP BY attribute_group_id";
            } else {
                for (EventProfileRule eventProfileRule : rules) {
                    StrBuilder strBuilder = new StrBuilder();
                    strBuilder.append("SELECT attribute_group_id FROM event_list WHERE event_id = \"").append(info.getEventId())
                            //todo 时间固定 操作符固定
                            .append("\" AND create_time >= \"2022-07-18 08:40:50\"  AND create_time <= \"2023-09-09 08:40:50\" AND attribute_id = \"").append(eventProfileRule.getAttributeId()).append("\" AND attribute_value = \"").append(eventProfileRule.getValue()).append("\" GROUP BY attribute_group_id");
                    eventProfileSql.add(strBuilder.toString());
                }
                StrJoiner strJoiner = new StrJoiner(" UNION ");
                //todo or用union and用join，如果每一个事件元数据放到一张表中，可以考虑使用宽表
                if ("or".equals(profileRule.getRelation())) {
                    eventProfileSql.forEach(strJoiner::append);
                }
                containSql = strJoiner.toString();
            }

            EventFilter filters = info.getFilters();
            String filtersSql = " HAVING COUNT(0) > 100 ";
            if ("unique".equals(filters.getOperator())) {
                filtersSql = "HAVING approx_count_distinct(create_day) > 50";
            }
            StrBuilder sql = new StrBuilder();
            sql.append("SELECT attribute_value FROM event_list WHERE event_id = \"").append(info.getEventId()).append("\" AND attribute_id = \"$element_name\" ").append(" AND attribute_group_id IN (").append("SELECT * FROM (").append(containSql).append(" ) a ) GROUP BY attribute_value ").append(filtersSql);
            sqlList.add(sql.toString());
        });
        return sqlList;
    }

}
